package com.alinks.modbus.device.storage;

import com.alinks.modbus.device.fatory.MemoryFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;

public final class DeviceManager {

    private final Map<Byte, Device> DEVICE_MAP = new HashMap<>();

    private static volatile DeviceManager DEVICEMANAGER = null;

    public static DeviceManager newInstance() {
        if (DEVICEMANAGER == null) {
            synchronized (DeviceManager.class) {
                if (DEVICEMANAGER == null) {
                    DEVICEMANAGER = new DeviceManager();
                }
            }
        }
        return DEVICEMANAGER;
    }

    public Device get(byte deviceId) {
        Device device = this.DEVICE_MAP.get(deviceId);
        if (device == null) {
            synchronized (DEVICEMANAGER) {
                device = new Device();
                device.setDeviceId(deviceId);
                device.setMemory(MemoryFactory.create());
                this.DEVICE_MAP.put(deviceId, device);
            }
        }
        return device;
    }

    public Device remove(byte deviceId) {
        return this.DEVICE_MAP.remove(deviceId);
    }

    public void write(byte deviceId, byte func, int start, byte[] data) {
        Device device = get(deviceId);
        switch (func) {
            case 05:
            case 15: {
                device.getMemory().writeCoil(start, data);
            } break;
            case 06:
            case 16: {
                device.getMemory().writeReg(start, data);
            } break;
            default: return;
        }

    }

    public byte[] read(byte deviceId, byte func, int start, int length) {
        Device device = get(deviceId);
        switch (func) {
            case 01:
            case 02: {
                return device.getMemory().readCoil(func, start, start + length);
            }
            case 03:
            case 04: {
                return device.getMemory().readReg(func, start, start + length);
            }
            default: return new byte[0];
        }
    }
}
